package cn.itsource.hrm.service.impl;

import cn.itsource.hrm.domain.CourseType;
import cn.itsource.hrm.mapper.CourseTypeMapper;
import cn.itsource.hrm.service.ICourseTypeService;
import cn.itsource.hrm.vo.CrumbsVo;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author yaosang
 * @since 2022-01-06
 */
//@Service
public class CourseTypeServiceImpl_02_springcache extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    private CourseTypeMapper courseTypeMapper;
    private static  final  String COURSETYPE_TREEDATA_IN_CACHE = "courseType_treeData_in_cache";//redis的key

    //    @Override //对某个id的课程类型进行缓存
    //    @Cacheable(cacheNames = COURSETYPE_TREEDATA_IN_CACHE,key = "#id")
    //    add(User user)
    @Override //对所有课程类型树进行缓存
    @Cacheable(cacheNames = COURSETYPE_TREEDATA_IN_CACHE,key = "'ALL'")
    public List<CourseType> treeData(Long pid) {
        //方案3：循环
        return loadTreeDataByLood(pid);
        //方案2：递归sql
        //return courseTypeMapper.loadTreeData(pid);
        //方案1：递归代码
        //return loadTreeDataByRecursion(pid);
    }

    @Override
    public List<CrumbsVo> queryCrumbs(Long typeId) {
        return null;
    }

    //方案3：循环方案
    private List<CourseType> loadTreeDataByLood(Long pid) {
        //1 定义返回列表
        List<CourseType> result = new ArrayList<>();
        //2 查询所有节点
        List<CourseType> allCourseTypes = courseTypeMapper.selectList(null);
        Map<Long,CourseType> courseTypeDto = new HashMap<>();//id-CourseType
        allCourseTypes.forEach(courseType -> {
            courseTypeDto.put(courseType.getId(),courseType);
        });
        //3 遍历所有节点判断是否是一级节点 当前类型pid是传入pid
        allCourseTypes.forEach(courseType -> { //算法时间复杂度 10 O(n2)
            //3.1 如果是放入返回列表
            Long ppid = courseType.getPid();
            if (ppid.longValue()==pid.longValue())
                result.add(courseType);
            //3.2 如果不是，放入父亲儿子集合
            else{
                //1)获取到父亲
                /*
                CourseType parent = allCourseTypes.stream()
                        .filter(courseTypeTmp -> courseTypeTmp.getId().longValue() == ppid.longValue())
                        .findFirst()
                        .get();*/
                /*方案1：ppid依次和所有节点的id进行比对，如果比对上就是父亲
                  CourseType parent = null;
                for (CourseType courseTypeTmp : allCourseTypes) { //10
                    if (courseTypeTmp.getId().longValue()==ppid.longValue()){
                        parent = courseTypeTmp;
                        break;
                    }
                }*/
                //方案2：转换为map再来获取数据 O(2n)
                CourseType parent = courseTypeDto.get(ppid);
                //2)获取到父亲儿子集合，把自己作为一个儿子放进去
                parent.getChildren().add(courseType);
            }

        });
        //4 返回“返回列表”
        return result;

    }


    //递归获取类型树
    //1 自己调用自己
    //2 要有出口
    private List<CourseType> loadTreeDataByRecursion(Long pid) {

        List<CourseType> courseTypes = courseTypeMapper
                .selectList(new EntityWrapper<CourseType>().eq("pid", pid));
        //出口
        if (courseTypes==null|| courseTypes.size()<1)
            return null;

        courseTypes.forEach(courseType -> {
            Long ppid = courseType.getId();
            //自己调用自己
            List<CourseType> children = loadTreeDataByRecursion(ppid);
            courseType.setChildren(children);
        });

        return courseTypes;

    }

    @Override //清除缓存
    //beforeInvocation = false 是否是先操作缓存，默认是false，先操作数据库再操作缓存
    @CacheEvict(cacheNames = COURSETYPE_TREEDATA_IN_CACHE,key = "'ALL'",beforeInvocation = false)
    public boolean insert(CourseType entity) {
        //先操作数据库，还是先操作缓存
        return super.insert(entity);
    }

    @Override
    @CacheEvict(cacheNames = COURSETYPE_TREEDATA_IN_CACHE,key = "'ALL'")
    public boolean deleteById(Serializable id) {
        return super.deleteById(id);
    }

    @Override
    @CacheEvict(cacheNames = COURSETYPE_TREEDATA_IN_CACHE,key = "'ALL'")
    public boolean updateById(CourseType entity) {
        return super.updateById(entity);
    }
}
